#!/usr/bin/env node
const { join, resolve, dirname } = require('path');
const { mkdirSync, readFileSync, rmSync, writeFileSync, readdirSync } = require('fs');
const { valid, lte, rcompare, prerelease, major, minor, patch } = require('semver');
const glob = require('glob');

const ROOT = resolve(__dirname, '..');

function camelCaseToSentenceCase(str)
{
    const tmp = str.replace(/([A-Z])/g, ' $1');

    return tmp.charAt(0).toUpperCase() + tmp.slice(1);
}

function camelCaseToSnakeCase(str)
{
    return str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
}

async function go()
{
    // Find all pixi-version.json files
    const versionFiles = glob.sync(`${ROOT}/**/pixi-version.json`);
    const EXAMPLES_PATH = resolve(ROOT, 'src', 'examples');

    // Read the directories in the examples directory
    const exampleDirectories = readdirSync(EXAMPLES_PATH, { withFileTypes: true })
        .filter((dirent) => dirent.isDirectory())
        .map((dirent) => dirent.name);

    // Perform the script on all the directories that they are in
    for (const versionFile of versionFiles)
    {
        const DOCS_PATH = dirname(versionFile);
        const EXAMPLES_MD_PATH = resolve(DOCS_PATH, 'examples');
        const pixiVersion = require(versionFile);
        const VERSION = pixiVersion.version;
        const isPrerelease = prerelease(`v${VERSION}`);
        const versionToCompare = isPrerelease ? `v${major(VERSION)}.${minor(VERSION)}.${patch(VERSION)}` : `v${VERSION}`;

        // Filter and sort the directories to find the best match
        const bestMatch = exampleDirectories
            // eslint-disable-next-line no-loop-func
            .filter((name) => valid(name) && lte(name, versionToCompare))
            .sort((a, b) => rcompare(a, b))[0];

        console.log(`Generating examples for v${VERSION} using the ${bestMatch} source`);

        const EXAMPLES_JS_PATH = resolve(EXAMPLES_PATH, bestMatch);

        const examplesData = require(`${EXAMPLES_JS_PATH}/examplesData.json`);

        const directories = Object.keys(examplesData);

        const directoryData = directories.map((directoryKey) =>
        {
            const categoryExamples = examplesData[directoryKey];
            const directoryName = camelCaseToSnakeCase(directoryKey);
            const categoryTitle = camelCaseToSentenceCase(directoryKey);

            return {
                categoryTitle,
                directoryPath: join(EXAMPLES_MD_PATH, directoryName),
                examples: categoryExamples.map((exampleData) =>
                {
                    let exampleKey = exampleData;
                    let usesWebWorkerLibrary = false;
                    let hide = false;

                    if (typeof exampleData !== 'string')
                    {
                        ({ name: exampleKey, usesWebWorkerLibrary = false, hide = false } = exampleData);
                    }

                    const mdFile = `${camelCaseToSnakeCase(exampleKey)}.md`;
                    const mdPath = join(EXAMPLES_MD_PATH, directoryName, mdFile);

                    return {
                        exampleKey: `${directoryKey}.${exampleKey}`,
                        examplePath: mdPath,
                        exampleTitle: camelCaseToSentenceCase(exampleKey),
                        hide,
                        usesWebWorkerLibrary,
                    };
                }),
            };
        });

        directoryData.forEach(({ categoryTitle, directoryPath, examples }, index) =>
        {
            // delete old stuff first
            rmSync(directoryPath, { recursive: true, force: true });

            // recreate directory and build everything
            mkdirSync(directoryPath);

            const categoryYml = [`label: ${categoryTitle}`, `position: ${index + 1}`].join('\n');
            const categoryYmlPath = join(directoryPath, '_category_.yml');

            writeFileSync(categoryYmlPath, categoryYml, 'utf8');

            let sidebarPosition = 0;

            examples.forEach(({ exampleKey, examplePath, exampleTitle, hide, usesWebWorkerLibrary }) =>
            {
                if (hide)
                {
                    return;
                }

                const webWorkerProp = usesWebWorkerLibrary ? ' usesWebWorkerLibrary' : '';

                const mdContents = [
                    '---',
                    'hide_table_of_contents: true',
                    'hide_edit_this_page: true',
                    `sidebar_position: ${sidebarPosition++}`,
                    'custom_edit_url: null',
                    `title: ${exampleTitle}`,
                    '---',
                    '<!-- AUTO-GENERATED BY [generate-example-docs] script -->',
                    'import Example from \'@site/src/components/Example/index\';',
                    'import version from \'../../pixi-version.json\';',
                    '',
                    `<Example id="${exampleKey}" pixiVersion={version}/>`,
                    '',
                ].join('\n');

                writeFileSync(examplePath, mdContents, 'utf8');
            });
        });
    }
}

go();
